
`ifdef FLIPFLOP
`else
`include "flipflop.v"
`define FLIPFLOP
`endif

`ifdef DECODER
`else
`include "decoder.v"
`define DECODER
`endif

`ifdef COMPARER
`else
`include "comparer.v"
`define COMPARER
`endif

`ifdef ENCODER
`else
`define ENCODER
`include "encoder.v"
`endif

`ifdef MULTIPLEXOR
`else
`define MULTIPLEXOR
`include "multiplexor.v"
`endif


module branchPredictor(clock,pcActualIn,pcActualwrIn,pcPredIn,takenIn,we,bphit,takenOut,pcPredOut,reset);
input[15:0] pcActualIn;
input[15:0] pcActualwrIn;
input[15:0] pcPredIn;
input takenIn,we,clock,reset;
output bphit,takenOut;
output[15:0] pcPredOut;

	wire wAndWeIndxOut0;
	wire wAndWeIndxOut1;
	wire wAndWeIndxOut2;
	wire wAndWeIndxOut3;
	wire wAndWeIndxOut4;
	wire wAndWeIndxOut5;
	wire wAndWeIndxOut6;
	wire wAndWeIndxOut7;

	wire [32:0] wFlipFlopOut0;
	wire [32:0] wFlipFlopOut1;
	wire [32:0] wFlipFlopOut2;
	wire [32:0] wFlipFlopOut3;
	wire [32:0] wFlipFlopOut4;
	wire [32:0] wFlipFlopOut5;
	wire [32:0] wFlipFlopOut6;
	wire [32:0] wFlipFlopOut7;

	wire [7:0] wDecoder;
	wire [15:0] wMultiplexorOut;
	wire wPredOut;

	wire wComparerAnd;

	wire wRstOut0;
	wire wRstOut1;
	wire wRstOut2;
	wire wRstOut3;
	wire wRstOut4;
	wire wRstOut5;
	wire wRstOut6;
	wire wRstOut7;

	Decoder3x8 decoder(pcActualwrIn[2:0],wDecoder);  
	
	and andWeIndx0(wAndWeIndxOut0,we,wDecoder[0]);
	and andWeIndx1(wAndWeIndxOut1,we,wDecoder[1]);
	and andWeIndx2(wAndWeIndxOut2,we,wDecoder[2]);
	and andWeIndx3(wAndWeIndxOut3,we,wDecoder[3]);
	and andWeIndx4(wAndWeIndxOut4,we,wDecoder[4]);
	and andWeIndx5(wAndWeIndxOut5,we,wDecoder[5]);
	and andWeIndx6(wAndWeIndxOut6,we,wDecoder[6]);
	and andWeIndx7(wAndWeIndxOut7,we,wDecoder[7]);
	
	
	Flip_flop_reset_enable33 FF0(clock,wFlipFlopOut0,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut0,reset);
	Flip_flop_reset_enable33 FF1(clock,wFlipFlopOut1,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut1,reset);
	Flip_flop_reset_enable33 FF2(clock,wFlipFlopOut2,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut2,reset);
	Flip_flop_reset_enable33 FF3(clock,wFlipFlopOut3,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut3,reset);
	Flip_flop_reset_enable33 FF4(clock,wFlipFlopOut4,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut4,reset);
	Flip_flop_reset_enable33 FF5(clock,wFlipFlopOut5,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut5,reset);
	Flip_flop_reset_enable33 FF6(clock,wFlipFlopOut6,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut6,reset);
	Flip_flop_reset_enable33 FF7(clock,wFlipFlopOut7,{takenIn,pcActualwrIn,pcPredIn},wAndWeIndxOut7,reset);


	Biestable_reset_enable R0(clock,reset,wRstOut0,1,wAndWeIndxOut0);
	Biestable_reset_enable R1(clock,reset,wRstOut1,1,wAndWeIndxOut1);
	Biestable_reset_enable R2(clock,reset,wRstOut2,1,wAndWeIndxOut2);
	Biestable_reset_enable R3(clock,reset,wRstOut3,1,wAndWeIndxOut3);
	Biestable_reset_enable R4(clock,reset,wRstOut4,1,wAndWeIndxOut4);
	Biestable_reset_enable R5(clock,reset,wRstOut5,1,wAndWeIndxOut5);
	Biestable_reset_enable R6(clock,reset,wRstOut6,1,wAndWeIndxOut6);
	Biestable_reset_enable R7(clock,reset,wRstOut7,1,wAndWeIndxOut7);


 Multiplexor8x1x34 multiplexor({wRstOut0,wFlipFlopOut0},{wRstOut1,wFlipFlopOut1},{wRstOut2,wFlipFlopOut2},{wRstOut3,wFlipFlopOut3},{wRstOut4,wFlipFlopOut4},{wRstOut6,wFlipFlopOut5},{wRstOut6,wFlipFlopOut6},{wRstOut7,wFlipFlopOut7},{wPredOut,takenOut,wMultiplexorOut,pcPredOut},pcActualIn[2:0]);

	Comparer16x1 comparer(wMultiplexorOut[15:0],pcActualIn,wComparerAnd);	

	and andComparerPred(bphit,wComparerAnd,wPredOut);


endmodule
